
#include "pub_var.h"
#include <QSize>
#include <QMessageBox>
#include <QDebug>
#include <QDate>
#include <QRegExp>
//#include <QTableWidget>
//#include <QTableWidgetItem>
#include <QTableView>

#include "sm4.h"


QSqlDatabase pub::db_m = QSqlDatabase::addDatabase("QMYSQL","pub::db_m");
QSqlDatabase pub::db_o = QSqlDatabase::addDatabase("QOCI","pub::db_o");
QSqlQuery pub::qr = QSqlQuery(pub::db_m);
//QSqlQueryModel pub::md = QSqlQueryModel::setQuery(qr);

//bool pub::DEBUG = false;  //调试标志
pub::pIT pub::BUSINESS = NULL;

pub::pInit pub::Init = NULL;
pub::pDailySinIn pub::DailySinIn = NULL;
pub::pEcQuery pub::EcQuery = NULL;
pub::pReadSFZ pub::ReadSFZ = NULL;
pub::pReadCardBas pub::ReadCardBas = NULL;
pub::pChangePIN pub::ChangePIN = NULL;

//bool pub::useInsurance = true;
bool pub::useInsurance = false;

QString pub::ybywzq = "";       //医保业务周期号
QString pub::ybywzqAtinc = "";  //交易atinc
QString pub::localIP = "";
QString pub::localMac = "";
QString pub::hos_name = "";    //医院名称
QString pub::hos_code = "";    //医院编码
QString pub::hos_ybbh_old = "";    //医院医保编号（旧）
QString pub::hos_ybbh = "";    //医院医保编号
QString pub::usr_name = "";    //用户姓名
QString pub::usr_code = "";    //用户代码
QString pub::dp_name = "";    //科室名称
QString pub::dp_code = "";    //科室代码
QString pub::LOGINSESSION = ""; //登录session
//QString pub::hos_ybbh_new = "";    //贯标医保编号
QString pub::hos_ybjy = "";    //医保交易中台
QString pub::hos_dzpz = "";    //电子凭证中台
QString pub::hos_ybjy_ip = "";    //医保交易中台
QString pub::hos_ybjy_port = "";    //医保交易中台
QString pub::hos_ybjy_tail = "";    //医保交易中台
QString pub::hos_dzpz_ip = "";    //电子凭证中台
QString pub::hos_dzpz_port = "";    //电子凭证中台
QString pub::hos_dzpz_tail = "";    //电子凭证中台
QString pub::hos_insuplc = "";  //参保区划
QString pub::local_carddriver = "";  //本机读卡器型号
QString pub::hos_hiscode = ""; //  开发商代码
QString pub::hos_secretcode = ""; //  安全管理码


bool pub::userValidated = false;   //用户身份验证

QString pub::sign_no = ""; //医保登录ID
QString pub::sign_time = ""; //医保登录ID


bool pub::cardFinish;
int pub::cardResult = -1;
QString pub::cardRet1 = ""; //
QString pub::cardRet2 = ""; //


QString pub::getStr(QString sour,QString sep,int ct)
{
    //sour: 源串
    //sep: 分隔符
    //ct: 返回被 sep 分隔的第 ct 个字串, 1 起始。
    if(sour.length() == 0){
        QMessageBox::information(NULL,"Note","pub::getStr:参数无效，源串不能为空！");
        return "";
    }
    if(sep.length() == 0){
        QMessageBox::information(NULL,"Note","pub::getStr:参数无效，字串分隔符不能为空！");
        return "";
    }
    if(ct < 1){
        QMessageBox::information(NULL,"Note","pub::getStr:参数无效，字序号不能小于1 ！");
        return "";
    }

    QStringList strs = sour.split(sep);
    if(ct > strs.size() ){
        return "";
    }
    return strs.takeAt(ct - 1);
}

int pub::searchStr(QString sour,QString sep,QString dest)
{
    //sour: 源串
    //sep: 分隔符
    //dest: 目标字串
    //返回索引位置，1 起始

    if(sour.length() == 0){
        QMessageBox::information(NULL,"Note","pub::searchStr:参数无效，源串不能为空！");
        return 0;
    }
    if(sep.length() == 0){
        QMessageBox::information(NULL,"Note","pub::searchStr:参数无效，字串分隔符不能为空！");
        return 0;
    }
    if(dest.length() == 0){
        QMessageBox::information(NULL,"Note","pub::searchStr:参数无效，目标字串不能为空！");
        return 0;
    }

    QStringList strs = sour.split(sep);
    return strs.indexOf(dest) + 1;

}

QString pub::getYbStr(QString s, QString code)
{
    //入参：s 医保交易号， code 当前clinicCode
    QString sq;
    QString ret;
    qDebug()<<"申请医保交易流水号：交易代码，clinic_code"<<s<<code;
    sq = "call yb_jylsh('" + hos_ybbh + "','" + usr_code + "','" + s +"','"+ ybywzq + "','"+ code + "')";

    if(!qr.exec(sq)){
        QMessageBox::information(NULL,"Note","pub::getYbStr: SQL return error!");
        qDebug()<<sq;
        return "";
    }
    qr.next();
    ret = qr.value(0).toString();
    if(ret.isEmpty()){
        QMessageBox::information(NULL,"Note","申请医保交易流水号错误!");
        return "";
    }
    ret = s + "^" + hos_ybbh + "^" + usr_code + "^" + ybywzq + "^" + ret + "^0000^";
    ybywzqAtinc = qr.value(1).toString();   //申请交易流水的atinc，待补全中心返回交易流水用。
    qDebug()<<"申请成功。 ybywzqAtinc"<<ybywzqAtinc;
    return ret;
}

QString pub::getYbStrJ(QString s, QString code)
{
    //
    QString sq;
    QString ret;
    qDebug()<<"申请医保交易流水号：交易代码，clinic_code"<<s<<code;
    sq = "call yb_jylshj('" + hos_ybbh + "','" + usr_code + "','" + s +"','ybywzq','"+ code + "')";

    if(!qr.exec(sq)){
        //QMessageBox::information(NULL,"Note","pub::getYbStrJ: SQL return error!");
        qDebug()<<sq;
        return "";
    }
    qr.next();
    ret = qr.value(0).toString();
    if(ret.isEmpty()){
        QMessageBox::information(NULL,"Note", s + " in ybGetStrJ 申请医保交易流水号错误!");
        return "";
    }
    //ret = s + "^" + hos_ybbh + "^" + usr_code + "^" + ybywzq + "^" + ret + "^0000^";
    ybywzqAtinc = qr.value(1).toString();   //申请交易流水的atinc，待补全中心返回交易流水用。
    qDebug()<<"申请成功。 ybywzqAtinc"<<ybywzqAtinc;
    return ret;
}

QStringList pub::getNl(QString s)
{
    QStringList ret;
    int strLen = s.length();
    if( strLen != 8 && strLen != 10){
        QMessageBox::information(NULL,"错误","年龄转换输入参数长度不正确："+s);
        return ret;
    }

    QDate cDate = QDate().currentDate();
    QDate sDate;
    if(strLen == 8){
        sDate = QDate().fromString(s,"yyyyMMdd");
    }else{
        sDate = QDate().fromString(s,"yyyy/MM/dd");
        if(!sDate.isValid()){
            sDate = QDate().fromString(s,"yyyy-MM-dd");
            if(!sDate.isValid()){
                QMessageBox::information(NULL,"错误","年龄转换输入无效日期："+s);
                return ret;
            }
        }
    }


    //QDate sDate = QDate().fromString(s);
    if(!sDate.isValid()){
        QMessageBox::information(NULL,"错误","年龄转换输入无效日期："+s);
        return ret;
    }
    int day = sDate.daysTo(cDate);
    if(day > 365 ){
        ret << QString::number(int(day/365))<<"岁";
    }else if(day>30){
        ret << QString::number(int(day/30))<<"月";
    }else if(day>=0){
        ret << QString::number(day)<<"天";
    }else{
        QMessageBox::information(NULL,"错误","年龄转换输入日期大于当前日期："+s);
    }
    return ret;
}
QString pub::getBirth(QString s)
{
    QDate cDate ;
    QRegExp re;
    int day ;

    re = QRegExp("^[1-9]\\d*[岁|月|天]?$");
    if(!re.exactMatch(s)){
        QMessageBox::information(NULL,"错误","年龄输入格式不正确："+s);
        return "";
    }
    re = QRegExp("^[1-9]\\d*");
    re.indexIn(s);
    day = re.cap().toInt();

    if( day > 100){     //不应出现大于100岁的年龄
        return "";
    }

    re = QRegExp("[岁|月|天]*$");
    re.indexIn(s);
    QString u = re.cap();
    u = u.isEmpty() ? "岁" : u;
    if( u == "岁" ){
        day = day * 365.3;
    }else if( u == "月"){
        day = day * 30.5;
    }

    cDate = QDate().currentDate().addDays( 0 - day);

    return cDate.toString("yyyyMMdd");
}

QString pub::popItem(QStringList itms)
{
    //参数约定：每行字段间以“^”分隔
    //QTableWidget wgt(NULL);

    //QTableView tbw(NULL);
    //tbw.setModel()
}

QString pub::popSql(QString sq)
{
    //参数约定：每行字段间以“^”分隔

//    QTableView tbw(NULL);
//    md.setQuery(sq);
//    tbw.setModel(&md);

//    int rowsCount = md.rowCount();
//        if(rowsCount == 0){
//            QMessageBox::information(NULL,"注意","未找到指定信息的相关记录！");
//            return "";
//        }else if(rowsCount == 1){

//        }


//        else{

//            md.setHeaderData(0, Qt::Horizontal, "身份证号");
//            md.setHeaderData(1, Qt::Horizontal, "姓名");
//            md.setHeaderData(2, Qt::Horizontal, "性别");
//            md.setHeaderData(3, Qt::Horizontal, "病志号");

//            int a = this->font().pointSize();
//            ui->tbId->setModel(&md);
//            ui->tbId->setColumnWidth(0,16*a);
//            ui->tbId->setColumnWidth(1,8*a);
//            ui->tbId->setColumnWidth(2,4*a);
//            ui->tbId->setColumnWidth(3,12*a);

//     //       ui->tbId->resizeColumnsToContents();
//        }
//        if(rowsCount == 1){ //if there only one record, fill it directly.

//            QModelIndex idx;
//            idx = md.index(0, 0);//
//            on_tbId_doubleClicked(idx);

//        }


}

QString pub::add0(QString s, int len)//增加数字前导0
{
    for(int c = s.length(); c < len; c ++ ){
        s = "0" + s;
    }
    return s;
}

QString pub::bigW(float x)   //数字转大写
{
    QRegExp re ;
    QString ret,base,base2,lead;
    base="零壹贰叁肆伍陆柒捌玖拾";
    base2="万仟佰拾元角分";
    //负数的处理
    if(x+0.0001<0){
        lead="负";
        x=0-x;
    }else{
        lead="";
    }
    int yuan = 0, j = 0, f = 0;		//元角分
    QString xx = QString::asprintf("%.2f", x); //浮点转字串

    re = QRegExp("^[1-9]\\d*"); //匹配前导数字
    re.indexIn(xx);
    yuan = re.cap().toInt();
    re = QRegExp(".\\d*$"); //匹配末尾数字
    re.indexIn(xx);
    QString jf = re.cap();  //含小数点的角分
    j = jf.mid(1,1).toInt();
    f = jf.mid(2,1).toInt();

    int tmpUp,tmpDown,big,count;
    bool appear0,start=false;		//0标志，转换开始标志
    big=10000;
    count=0;
    //整数部分
    while(big>0){
        tmpUp = yuan / big;		    //取当前最高位数
        tmpDown = yuan % big;		//取余数
        yuan=tmpDown;
        if(tmpUp>0){                //当前位数大于0
            ret=ret+base.mid(tmpUp,1)+base2.mid(count,1);
            start=true;
            appear0=false;
        }
        if(start){		//高位 0 已经全部排除
            if(tmpUp==0 && big==10000){
                ret=ret+"万";
            }
            if(tmpUp==0 && tmpDown == 0 && j==0 && f == 0){	//此后无有效数位
                if(big>=10000){
                    ret=ret+"万元";
                }else{
                    ret=ret+"元";
                }
                break;
            }else if(tmpUp==0 && tmpDown ==0 && (j>=0 || f>0 )){
                //此后无有效整数位，但有角分
                ret=ret+"元零";
                //0标记，用于小数位打印。循环退出之前设置，不会对下个判断造成干扰
                appear0=true;
                break;
            }else if(!appear0 && tmpUp==0 && tmpDown >0 ){
                //连续 0 中的第 1 个 ，此后还有有效整数位
                ret=ret+"零";
                appear0=true;
            }
        }
        big/=10;
        count++;
    }
    //小数部分
    if(j != 0 || f!= 0){		//角不为 0  或分不为 0
        if( j==0 ){		//角为0
            if( !appear0 ){     //最后整数位非零
                ret=ret+"零";
            }
            //角为 0 ，最后整数位已经有零则不需要处理
        }else {
            ret=ret+base.mid(j,1)+"角";
        }
        ret=ret+base.mid(f,1)+"分";
    }else{
        ret=ret+"整";
    }
    if(ret == "整"){
        ret = "零元";
    }
    return lead+ret;
}

QString pub::getValueFromList(QStringList lst, QString str)
{
    QString ret = "";
    foreach(QString i, lst){
        if(pub::getStr(i,"^",1) == str){
            ret = pub::getStr(i,"^",2);  //
            break;
        }
    }
    return ret;
}

//加密函数（可以加密任意长度数据，16字节为一次循环，不足部分补0凑齐16字节的整数倍）
//len:数据长度(任意长度数据) key:密钥（16字节） input:输入的原始数据 output:加密后输出数据
//QString pub::encode(QString inp, QString key)
QString pub::encode(QByteArray inp, QByteArray key)
{
    if(inp.isEmpty()){
        QMessageBox::information(NULL,"注意","encode 输入的字串为空！");
        return "";
    }
    if(key.length() != 16){
        QMessageBox::information(NULL,"注意","encode 输入的 key 长度错误！");
        return "";
    }
    int len;
    //QByteArray inpu = inp.toUtf8();
    QByteArray inpb = pkcs7_padding(inp);//inp.toLatin1().data()
    //QByteArray inpb = pkcs7_padding(inp.toLocal8Bit().data());
    len = inpb.length();

    //QByteArray k = key.toLatin1();
    QByteArray outpb;
    QByteArray split;
    unsigned char *out = new unsigned char [len];
    for (int j = 0; j < len / 16 ; j++){
        split = inpb.mid(j * 16, 16);

        for(int i = 0; i<16; i++){
            out[i + j*16] = split.at(i);
        }

        //outpb.append(enc(split, key).toLatin1());
        //outpb.append(enc(inpb.mid(j * 16, 16), k).toLocal8Bit());
//qDebug()<<QString::fromLatin1(split);
//qDebug()<<split.length();
//qDebug()<<outpb.length();
    }
    outpb = QByteArray::fromRawData((char*)out, len);
    QString ret = outpb.toBase64();
    delete []out;
    return ret;

}

QString pub::decode(QByteArray inp, QByteArray key)
{
    if(inp.isEmpty()){
        QMessageBox::information(NULL,"注意","decode 输入的字串为空！");
        return "";
    }
    if(key.length() != 16){
        QMessageBox::information(NULL,"注意","decode 输入的 key 长度错误！");
        return "";
    }
    QByteArray inpb = QByteArray::fromBase64(inp);
    //QByteArray inpb = QByteArray::fromBase64(inp.toLocal8Bit().data());
    int len = inpb.length();
    //QByteArray k = key.toLatin1();
    QByteArray outpb;

    QByteArray split;
    unsigned char *out = new unsigned char [len];
    for (int j = 0; j < len / 16 ; j++){
        split = inpb.mid(j * 16, 16);

        for(int i = 0; i<16; i++){
            out[i + j*16] = split.at(i);
        }

        //outpb.append(dec(inpb.mid(j * 16, 16), key).toLatin1());
        //outpb.append(dec(inpb.mid(j * 16, 16), k).toLocal8Bit());
    }
    outpb = QByteArray::fromRawData((char*)out, len);
qDebug()<<"decode out";
qDebug()<<QString::fromUtf8(outpb);
qDebug()<<QString::fromLatin1(outpb);
qDebug()<<QString::fromLocal8Bit(outpb);
    QString ret = QString::fromLatin1(pkcs7_strip(outpb));
    delete [] out;
    return ret; //
}

QByteArray pub::pkcs7_padding(QByteArray content)
{
    // 待填充的长度
    int padding_size = 16 - ( content.length() % 16);

    // 待填充的字符
    for(int i = padding_size; i>0 ;i--){
        content.append(padding_size);
    }
qDebug()<<"padding_size"<<padding_size;
    return content;
}

QByteArray pub::pkcs7_strip(QByteArray content)
{
    unsigned char lastch = content.at(content.length() - 1);
qDebug()<<"lastch"<<lastch;
    while(lastch > 0){
        content.chop(1);
        lastch -- ;
    }
    return content;
}

//QByteArray pub::enc(QByteArray bs, QByteArray bk)
QString pub::enc(QByteArray bs, QByteArray bk)
{
    unsigned char * key  = (unsigned char *)bk.data();
    unsigned char * input  = (unsigned char *)bs.data();
    unsigned char output[16];
    sm4_context ctx;
    sm4_setkey_enc(&ctx, key);
    sm4_crypt_ecb(&ctx, 1, 16, input, output);
    QByteArray ret = QByteArray::fromRawData((char*) output, 16);
    return QString::fromLatin1(ret);
}

//QByteArray pub::dec(QByteArray bs, QByteArray bk)
QString pub::dec(QByteArray bs, QByteArray bk)
{
    unsigned char * output = (unsigned char *)bs.data();
    unsigned char * key  = (unsigned char *)bk.data();
    sm4_context ctx;
    sm4_setkey_dec(&ctx, key);
    sm4_crypt_ecb(&ctx, 0, 16, output, output);
    QByteArray ret = QByteArray::fromRawData((char*) output, 16);
    return QString::fromLatin1(ret);

}





